﻿using IceDog.UpdateDB.IRepository;
using IceDog.UpdateDB.Model;
using IceDog.UpdateDB.Model.Data;
using IceDog.UpdateDB.Model.Enums;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace IceDog.UpdateDB.Repository
{
    /// <summary>
    /// 基础仓储实现
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public partial class Repository<TModel> : IRepository<TModel> where TModel : BaseModel, new()
    {
        /// <summary>
        /// 运维数据库上下文
        /// </summary>
        public EFContext Context { get; }

        public Repository(EFContext context)
        {
            Context = context;
        }

        /// <summary>
        /// 添加模型
        /// </summary>
        /// <param name="model">模型</param>
        /// <returns>添加的模型</returns>
        public virtual TModel Add(TModel model)
        {
            Context.Entry(model).State= EntityState.Added;
            var rowCount = Context.SaveChanges();
            return rowCount > 0 ? model : null;
        }


        /// <summary>
        /// 批量添加模型
        /// </summary>
        /// <param name="models">模型列表</param>
        /// <returns>批量添加的模型</returns>
        public virtual List<TModel> Add(List<TModel> models)
        {
            foreach (var model in models)
            {
                Context.Entry(model).State = EntityState.Added;
            }
            var rowCount = Context.SaveChanges();
            return rowCount > 0 ? models : new List<TModel>();
        }
        /// <summary>
        /// 更新模型，根据模型modelId值更新
        /// </summary>
        /// <param name="model">模型</param>
        /// <returns>更新的模型</returns>
        public virtual TModel Update(TModel model)
        {
            if (!Exists(model.ModelID))
            {
                return null;
            }
            Context.Entry(model).State = EntityState.Modified;
            var rowCount = Context.SaveChanges();
            return rowCount > 0 ? model : null;
        }

        /// <summary>
        /// 批量更新模型，根据模型modelId值更新
        /// </summary>
        /// <param name="models">模型列表</param>
        /// <returns>更新的模型列表</returns>
        public virtual List<TModel> Update(List<TModel> models)
        {
            foreach (var model in models)
            {
                Context.Entry(model).State = EntityState.Modified;
            }
            var rowCount = Context.SaveChanges();
            return rowCount > 0 ? models : new List<TModel>();
        }

        /// <summary>
        /// 删除模型，根据模型modelId值删除
        /// </summary>
        /// <param name="modelId">模型Id</param>
        /// <returns>删除的模型数量</returns>
        public virtual int Delete(int modelId)
        {
            var model = SelectOne(modelId);
            if (model != null)
            {
                Context.Entry(model).State = EntityState.Deleted;
                return Context.SaveChanges();
            }
            return 0;
        }

        /// <summary>
        /// 删除模型，根据模型modelGuid值删除
        /// </summary>
        /// <param name="modelGuid">模型Guid</param>
        /// <returns>删除的模型数量</returns>
        public virtual int Delete(string modelGuid)
        {
            var model = SelectOne(modelGuid);
            if (model != null)
            {
                Context.Entry(model).State = EntityState.Deleted;
                return Context.SaveChanges();
            }
            return 0;
        }

        /// <summary>
        /// 批量删除模型，根据模型modelId值删除
        /// </summary>
        /// <param name="modelIds">模型id列表</param>
        /// <returns>删除的模型数量></returns>
        public virtual int Delete(List<int> modelIds)
        {
            var models = Select(m => modelIds.Contains(m.ModelID));
            foreach (var model in models)
            {
                Context.Entry(model).State = EntityState.Deleted;
                return Context.SaveChanges();
            }
            return 0;
        }

        /// <summary>
        /// 批量删除模型，根据模型modelId值删除
        /// </summary>
        /// <param name="modelIds">模型guid列表</param>
        /// <returns>删除的模型数量></returns>
        public virtual int Delete(List<string> modelGuids)
        {
            var models = Select(m => modelGuids.Contains(m.ModelGuid));
            foreach (var model in models)
            {
                Context.Entry(model).State = EntityState.Deleted;
                return Context.SaveChanges();
            }
            return 0;
        }

        /// <summary>
        /// 根据ModelId进行查找模型
        /// </summary>
        /// <param name="modelId">模型id</param>
        /// <returns>找到的模型，找不到为null</returns>
        public virtual TModel SelectOne(int modelId)
        {
            return Context.Set<TModel>().Find(modelId);
        }

        /// <summary>
        /// 根据modelGuid进行查找模型
        /// </summary>
        /// <param name="modelGuid">模型guid</param>
        /// <returns>找到的模型，找不到为null</returns>
        public virtual TModel SelectOne(string modelGuid)
        {
            return Context.Set<TModel>().FirstOrDefault(m=>m.ModelGuid.Equals(modelGuid));
        }

        /// <summary>
        /// 根据表达式进行查找第一个模型
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>找到的模型列表</returns>
        public virtual TModel SelectOne(Expression<Func<TModel, bool>> expression)
        {
            return Context.Set<TModel>().Where(expression).ToList().FirstOrDefault();
        }

        /// <summary>
        /// 根据表达式进行查找模型
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>找到的模型列表</returns>
        public virtual List<TModel> Select(Expression<Func<TModel, bool>> expression)
        {
            return Context.Set<TModel>().Where(expression).ToList();
        }

        /// <summary>
        /// 根据条件进行查找模型
        /// </summary>
        /// <typeparam name="TSortField">表达式给定的排序字段类型</typeparam>
        /// <param name="predicate">条件断言</param>
        /// <param name="sortFieldSelector">排序字段选择器</param>
        /// <param name="sortOrder">排序方式</param>
        /// <param name="pageNumber">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <returns>找到的模型列表和总数</returns>
        public virtual (List<TModel> results, long totalCount) Select<TSortField>(Expression<Func<TModel, bool>> predicate, Expression<Func<TModel, TSortField>> sortFieldSelector, SortOrder sortOrder, int pageNumber, int pageSize)
        {
            IQueryable<TModel> query = Context.Set<TModel>().Where(predicate);
            long totalCount = query.LongCount();
            List<TModel> results = new List<TModel>();
            if(sortOrder == SortOrder.Ascending)
            {
                query = query.OrderBy(sortFieldSelector);
            }
            if(sortOrder == SortOrder.Descending)
            {
                query = query.OrderByDescending(sortFieldSelector);
            }
            query.Skip((pageNumber - 1) * pageSize).Take(pageSize);
            results = query.ToList();

            return (results,totalCount);
        }

        /// <summary>
        /// 返回所有模型
        /// </summary>
        /// <returns></returns>
        public virtual List<TModel> SelectAll()
        {
            return Context.Set<TModel>().ToList();
        }

        /// <summary>
        /// 根据modelId判断模型是否存在
        /// </summary>
        /// <param name="modelId">模型id</param>
        /// <returns></returns>
        public virtual bool Exists(int modelId)
        {
            var count = Context.Set<TModel>().LongCount(m => m.ModelID == modelId);
            return count > 0;
        }

        /// <summary>
        /// 根据modelGuid判断模型是否存在
        /// </summary>
        /// <param name="modelGuid">模型guid</param>
        /// <returns></returns>
        public virtual bool Exists(string modelGuid)
        {
            var count = Context.Set<TModel>().LongCount(m => m.ModelGuid == modelGuid);
            return count > 0;
        }

        /// <summary>
        /// 根据modelGuid判断模型是否存在
        /// </summary>
        /// <param name="predicate">条件断言</param>
        /// <returns></returns>
        public virtual bool Exists(Expression<Func<TModel,bool>> predicate)
        {
            var count = Context.Set<TModel>().LongCount(predicate);
            return count > 0;
        }

        
    }
}
